package io.task.message.socket.spi.client;

import io.task.message.socket.ChannelContext;
import io.task.message.socket.thread.pool.DefaultThreadFactory;
import io.task.message.socket.thread.pool.SynThreadPoolExecutor;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.LinkedBlockingQueue;

@Slf4j
@Setter
@Getter
public class ReconnConf {

    public static ReconnConf getReconnConf(ClientChannelContext clientChannelContext) {
        ClientConfig tioClientConfig = (ClientConfig) clientChannelContext.config;
        ReconnConf reconnConf = tioClientConfig.getReconnConf();
        return reconnConf;
    }

    /**
     * @param clientChannelContext
     * @param putIfNeedConn        如果需要重连，则把该ClientChannelContext放到重连队列中
     * @return
     */
    public static boolean isNeedReconn(ClientChannelContext clientChannelContext, boolean putIfNeedConn) {
        if (clientChannelContext == null) {
            return false;
        }
        ReconnConf reconnConf = getReconnConf(clientChannelContext);
        if (reconnConf == null) {
            return false;
        }

        if (reconnConf.getInterval() > 0) {
            if (reconnConf.getRetryCount() <= 0 || reconnConf.getRetryCount() > clientChannelContext.getReconnCount().get()) {
                if (putIfNeedConn) {
                    ClientConfig tioClientConfig = (ClientConfig) clientChannelContext.config;
                    tioClientConfig.closeds.add(clientChannelContext);
                    clientChannelContext.stat.timeInReconnQueue = System.currentTimeMillis();
                    reconnConf.getQueue().add(clientChannelContext);
                }

                return true;
            } else {
                log.info("不需要重连{}", clientChannelContext);
                return false;
            }
        }

        return false;
    }

    /**
     * @param clientChannelContext
     * @return true:需要重连;     false:不需要重连
     */
    public static boolean put(ClientChannelContext clientChannelContext) {
        if (clientChannelContext == null) {
            return false;
        }

        //		ReconnConf reconnConf = ReconnConf.getReconnConf(clientChannelContext);
        return isNeedReconn(clientChannelContext, true);
    }

    /**
     * 重连的间隔时间，单位毫秒
     */
    private long interval = 5000;

    /**
     * 连续重连次数，当连续重连这么多次都失败时，不再重连。0和负数则一直重连
     */
    private int retryCount = 0;

    LinkedBlockingQueue<ChannelContext> queue = new LinkedBlockingQueue<>();

    /**
     * 用来重连的线程池
     */
    private volatile SynThreadPoolExecutor threadPoolExecutor = null;

    /**
     * @author tanyaowu
     */
    public ReconnConf() {
        if (threadPoolExecutor == null) {
            synchronized (ReconnConf.class) {
                if (threadPoolExecutor == null) {
                    //					threadPoolExecutor = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), Runtime.getRuntime().availableProcessors(), 60L, TimeUnit.SECONDS,
                    //							new LinkedBlockingQueue<Runnable>(), DefaultThreadFactory.getInstance("tio-client-reconn"));
                    //
                    //

                    LinkedBlockingQueue<Runnable> tioQueue = new LinkedBlockingQueue<>();
                    //			ArrayBlockingQueue<Runnable> tioQueue = new ArrayBlockingQueue<>(QUEUE_CAPACITY);
                    String tioThreadName = "tio-client-reconn";
                    DefaultThreadFactory defaultThreadFactory = DefaultThreadFactory.getInstance(tioThreadName, Thread.MAX_PRIORITY);

                    threadPoolExecutor = new SynThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), Runtime.getRuntime().availableProcessors(), 60L, tioQueue,
                            defaultThreadFactory, tioThreadName);
                    //			tioExecutor = new SynThreadPoolExecutor(AVAILABLE_PROCESSORS * 2, Integer.MAX_VALUE, 60, new SynchronousQueue<Runnable>(), defaultThreadFactory, tioThreadName);

                }
            }

        }

    }


}
